/* 

处理effect嵌套的情况
foo:fn1
bar:fn2

修改foo，应该导致fn1执行

解决：activeEffect改成栈的形式

*/

let data = {
    bar: 1,
    foo: 2
}
const weakMap = new WeakMap()
let activeEffect
let effectStack = []

data = new Proxy(data, {
    get(target, prop) {
        track(target, prop)
        return Reflect.get(...arguments)
    },
    set(target, prop, val) {
        Reflect.set(...arguments)
        trigger(target, prop)
    }
})

function track(target, prop) {
    if (!activeEffect) return
    if (!weakMap.has(target)) weakMap.set(target, new Map())
    const map = weakMap.get(target)
    if (!map.has(prop)) map.set(prop, new Set())
    const set = map.get(prop)
    set.add(activeEffect)
    activeEffect.deps.push(set)
}

function trigger(target, prop) {
    const set = weakMap.get(target)?.get(prop)
    if (!set) return
    const newSet = new Set()
    set.forEach(fn => newSet.add(fn));
    newSet.forEach(fn => fn())
}

function effect(fn) {
    const wrapper = function () {
        wrapper.deps.forEach(set => {
            set.delete(activeEffect)
        })
        effectStack.push(wrapper)
        activeEffect = effectStack.at(-1)
        fn()
        effectStack.pop()
        activeEffect = effectStack.at(-1)
    }
    wrapper.deps = []
    wrapper()
}


effect(function fn1() {
    console.log('fn1执行');
    effect(function fn2() {
        console.log('fn2执行');
        console.log('读取data.bar', data.bar);
    })
    console.log('读取data.foo', data.foo);
})
console.log('-------');
console.log('修改data.foo');
data.foo = 1
